#include "main.h"
// 初始化名为s的栈，初始化成功，返回0，否则返回1。
bool is_operator(char symbol) {
    char operator[7] = {'+','-','*','/','(',')','#'};
    for(int i= 0; i<7; ++i)
    {
        if(operator[i] == symbol)
        {
            return 1;
        }
    }
    return 0;
}

// 判断刚扫描到的symbol是否操作数。如果symbol是操作数，返回1，否则返回0。
bool is_operand(char symbol) {
    char operand[10] = {'0','1','2','3','4','5','6','7','8','9'};
    for(int i= 0; i<10; ++i)
    {
        if(operand[i] == symbol)
        {
            return 1;
        }
    }
    return 0;
}

int init_stack(Stack *stack){
    (*stack)= malloc(sizeof(struct stack));
    int * p = (int*)malloc(STACK_MAX_SIZE*sizeof(int));
    (*stack)->base=p;
    if(!(*stack)->base)
        return 1;
    (*stack)->top=(*stack)->base;
    (*stack)->number_of_elements = STACK_MAX_SIZE;
    return 0;
}

// 入栈。返回值表示是否压栈成功：0，成功；1，不成功。
int push(Stack stack, char operator_or_operand) {
    if(stack->top-stack->base >= stack->number_of_elements) {
        return 1;
    }else {
        *(stack->top) = operator_or_operand;
        stack->top += 1;
        return 0;
    }
}


// 出栈。返回值表示是否出栈成功：0，成功，1，不成功。
int pop(Stack stack, char * p_operator_or_operand){
    if(stack->top==stack->base)
        return 1;
    stack->top-=1;
    *p_operator_or_operand=*(stack->top);
    return 0;
}

// 只返回栈顶元素，通过result变量返回栈顶元素的值。函数返回值用于表示执行状态：0，成功；1，不成功。

// 判断刚扫描到的symbol是否操作符。如果symbol是操作符，返回1，否则返回0。
int get_top(Stack stack, char * result) {
    if(stack->base==stack->top){
        return 1;
    }
    else{
        *result=*(stack->top-1);
        return 0;
    }
}


int compare(char operator_on_stack_top,char just_scanned_operator){//比较操作符
    int i, j;
    char priority[][7] = {
            /*运算符之间的优先级制作成一张表格*/
            {'>', '>', '<', '<', '<', '>', '>'},
            {'>', '>', '<', '<', '<', '>', '>'},
            {'>', '>', '>', '>', '<', '>', '>'},
            {'>', '>', '>', '>', '<', '>', '>'},
            {'<', '<', '<', '<', '<', '=', '0'},
            {'>', '>', '>', '>', '0', '>', '>'},
            {'<', '<', '<', '<', '<', '0', '='}
    };
    switch(operator_on_stack_top){
        case '+': i=0; break;
        case '-': i=1; break;
        case '*': i=2; break;
        case '/': i=3; break;
        case '(': i=4; break;
        case ')': i=5; break;
        case '#': i=6; break;
    }
    switch (just_scanned_operator) {
        case '+':j = 0;break;
        case '-':j = 1;break;
        case '*':j = 2;break;
        case '/':j = 3;break;
        case '(':j = 4;break;
        case ')':j = 5;break;
        case '#':j = 6;break;
    }
    switch (priority[i][j]) {
        case '>':
            return 1;
        case '<':
            return -1;
        case '=':
            return 0;

    }


}
int caculate(char operator,char left_operand,char right_operator,int *result){//计算操作数
    int i;
    int j;
    switch (left_operand) {
        case '0':i=0;break;
        case '1':i=1;break;
        case '2':i=2;break;
        case '3':i=3;break;
        case '4':i=4;break;
        case '5':i=5;break;
        case '6':i=6;break;
        case '7':i=7;break;
        case '8':i=8;break;
        case '9':i=9;break;

    }
    switch (right_operator) {
        case '0':j=0;break;
        case '1':j=1;break;
        case '2':j=2;break;
        case '3':j=3;break;
        case '4':j=4;break;
        case '5':j=5;break;
        case '6':j=6;break;
        case '7':j=7;break;
        case '8':j=8;break;
        case '9':j=9;break;

    }
    switch (operator) {
        case '+':*result=i+j;break;
        case '-':*result=i-j;break;
        case '*':*result=i*j;break;
        case '/':
        if(j!=0){
            *result=i/j;
        } else{
            printf("除数为零 错误！\n");
            exit(0);
        }
            break;
    }
    return 0;
    }

int evaluate(char * expression, int * result) {
    Stack OPTR;
    Stack OPND;
    char left_operand;
    char right_operand;
    init_stack(&OPTR);
    init_stack(&OPND);

    int char_position = 0;
    push(OPTR, expression[char_position]);
    char_position +=1;
    char top;
    char w = expression[char_position];

    while(w != '#' || top != '#')
    {
        if(is_operand(w))
        {
            push(OPND, w);
            char_position += 1;
            w = expression[char_position];
        }
        if(is_operator(w))
        {   char c;
            get_top(OPTR, &c);
            char Total;
            int RESULT;
            switch (compare(c,w)) {
                case -1:
                    push(OPTR, w);
                    w = expression[++char_position];
                    break;
                case 0:
                    pop(OPTR, &c);
                    w = expression[++char_position];
                    break;
                case 1:
                    pop(OPND, &right_operand);
                    pop(OPND, &left_operand);
                    pop(OPTR, &c);
                    if (c == '#' || left_operand == 0){
                        *result = 1;
                        return *result;
                    }else {
                        caculate(c, left_operand, right_operand, &RESULT);
                        Total = RESULT + 48;
                        push(OPND, Total);
                    }
                    break;
            }
        }
        get_top(OPTR, &top);
    }
    get_top(OPND, &top);
    *result = top - 48;
    return *result;
}

int main(int argc, char * argv[]) {
    int result;
    int is_exp_valid= evaluate("#1+(1+1)*3/2-2#", &result);
    printf("result:%d",is_exp_valid);
}

